﻿//SecurityStorage.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo.History
{
	using System;
	using System.Collections.Generic;

	using Ecng.Collections;
	using Ecng.Common;

	using StockSharp.Algo.History;
	using StockSharp.Algo.Storages;
	using StockSharp.BusinessEntities;

	/// <summary>
	/// Хранилище информации об инструментах.
	/// </summary>
	public class SecurityStorage : ISecurityStorage
	{
		private readonly SynchronizedDictionary<string, Security> _cacheById = new SynchronizedDictionary<string, Security>(StringComparer.InvariantCultureIgnoreCase);
		private readonly SynchronizedSet<Security> _nonSavedSecurities = new SynchronizedSet<Security>();

		/// <summary>
		/// Список инструментов.
		/// </summary>
		public IEnumerable<Security> CachedSecurities { get { return _cacheById.Values; } }

		/// <summary>
		/// Создать <see cref="SecurityStorage"/>.
		/// </summary>
		/// <param name="entityRegistry">Хранилище торговых объектов.</param>
		public SecurityStorage(IEntityRegistry entityRegistry)
		{
			if (entityRegistry == null)
				throw new ArgumentNullException("entityRegistry");

			foreach (var security in entityRegistry.Securities)
				AddToCache(security);
		}

		/// <summary>
		/// Загрузить информацию об инструменте из хранилища по полю и его значению.
		/// </summary>
		/// <param name="fieldName">Название поля, по которому необходимо загрузить информацию об инструменте.</param>
		/// <param name="fieldValue">Значение поля <paramref name="fieldName"/>.</param>
		/// <returns>Информация об инструменте.</returns>
		public virtual Security LoadBy(string fieldName, object fieldValue)
		{
			switch (fieldName)
			{
				case "Id":
					return _cacheById.TryGetValue((string)fieldValue);
				default:
					throw new NotSupportedException("Неподдерживаемое поле {0}.".Put(fieldName));
			}
		}

		/// <summary>
		/// Сохранить информацию об инструменте в хранилище.
		/// </summary>
		/// <param name="security">Информация об инструменте.</param>
		public virtual void Save(Security security)
		{
			if (security == null)
				throw new ArgumentNullException("security");

			_nonSavedSecurities.Add(security);

			if (!_cacheById.ContainsKey(security.Id))
				AddToCache(security);
		}

		private void AddToCache(Security security)
		{
			if (security == null)
				throw new ArgumentNullException("security");

			_cacheById.Add(security.Id, security);
		}

		/// <summary>
		/// Получить несохраненные инструменты.
		/// </summary>
		/// <returns>Несохраненные инструменты.</returns>
		public Security[] GetNonSavedSecurities()
		{
			return _nonSavedSecurities.SyncGet(c => c.CopyAndClear());
		}
	}
}